package pers.mihao.quickstream.common.plus.store;

import pers.mihao.quickstream.common.exception.BaseException;
import pers.mihao.quickstream.common.util.ReflectionUtil;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author mihao
 * @since 2022/8/22
 */
public abstract class AbstractStore implements Store {

    private volatile boolean isInit = false;

    @Override
    public int save(Object entry) {
        doInit();
        Serializable key = queryStoreKey(entry);
        return doSave(entry.getClass().getName(), key, entry);
    }

    protected abstract int doSave(String name, Serializable key, Object entry);

    private Serializable queryStoreKey(Object entry) {
        List<Field> fieldList = ReflectionUtil.listFields(entry.getClass()).stream()
                .filter(field -> field.getAnnotationsByType(StoreKey.class).length > 0)
                .filter(field -> field.getType().isAssignableFrom(Serializable.class))
                .distinct()
                .collect(Collectors.toList());
        
        if (fieldList.isEmpty()) {
            throw new BaseException();
        }
        List<Object> objects = fieldList.stream().map(field -> ReflectionUtil.getValueByField(entry, field))
                .collect(Collectors.toList());

        StringBuilder keyBuilder = new StringBuilder();
        for (Object obj : objects) {
            if (obj == null) {
                throw new BaseException();
            } else {
                keyBuilder.append(obj.toString()).append("|");
            }
        }
        return keyBuilder.toString();
    }

    @Override
    public Object query(Object object) {
        Serializable key = queryStoreKey(object);
        return null;
    }

    @Override
    public int delete(Serializable key) {
        doInit();
        return 0;
    }

    private void doInit() {
        if (!isInit) {
            synchronized (this) {
                if (!isInit) {
                    init();
                    isInit = true;
                }
            }
        }
    }

    protected abstract void init();
}
